package top.xphu.zip.service;

import top.xphu.zip.FileDownloadUtils;
import top.xphu.zip.entiy.BasaltFile;
import top.xphu.zip.entiy.ZFileInputStream;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 核心功能：打包，压缩，下载
 *
 * @author xphu
 * @version 1.0
 * @date 2021/7/2 15:38
 */
public class FilePackageCore {


    /**
     * 压缩文件对象
     */
    private BasaltFile basaltFile;

    /**
     * 构造对象
     *
     * @return
     */
    public static FilePackageCore build() {
        return new FilePackageCore();
    }

    /**
     * 设置打包文件对象
     *
     * @param basaltFile
     * @return this
     */
    public FilePackageCore setPackageFile(BasaltFile basaltFile) {
        this.basaltFile = basaltFile;
        return this;
    }

    /**
     * 创建设置打包文件对象
     *
     * @param packageName 压缩文件名称
     * @return this
     */
    public FilePackageCore createPackageFile(String packageName) {
        this.basaltFile = BasaltFile.buider().name(packageName).create();
        return this;
    }


    /**
     * 打包：打包文件流
     *
     * @param zFileInputStreams 文件输入流
     * @throws Exception
     */
    public FilePackageCore packageFileInputStreams(List<ZFileInputStream> zFileInputStreams) throws Exception {
        for (ZFileInputStream zFileInputStream : zFileInputStreams) {
            pressIn(zFileInputStream);
        }
        return this;
    }


    /**
     * 打包：打包文件
     *
     * @param files 输入文件
     * @throws Exception
     */
    public FilePackageCore packageFiles(List<File> files) throws Exception {
        for (File file : files) {
            pressIn(getZFileInputStream(file));
        }
        return this;
    }

    /**
     * 将输入文件打包到输出文件中
     *
     * @param zipFileInputStream 输入文件
     */
    public void pressIn(ZFileInputStream zipFileInputStream) throws IOException {
        if (zipFileInputStream == null) {
            throw new NullPointerException("输入的文件流不能为null");
        }

        InputStream is = zipFileInputStream.getFileBody();
        BufferedInputStream bis = null;
        try {
            if (is == null) {
                throw new NullPointerException("输出的文件流不能为null");
            }
            bis = new BufferedInputStream(is, 1024);
            this.basaltFile.getBody().setMethod(ZipOutputStream.DEFLATED);
            // 创建压缩文件对象
            ZipEntry zipEntry = new ZipEntry(zipFileInputStream.getFileName());
            this.basaltFile.getBody().putNextEntry(zipEntry);
            // 向压缩文件中输入数据
            int i = 0;
            byte[] bytes = new byte[1024];
            while ((i = bis.read(bytes)) != -1) {
                this.basaltFile.getBody().write(bytes, 0, i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bis.close();
            is.close();
        }
    }

    /**
     * 获取文件输入流
     *
     * @param file
     * @return top.xphu.zip.entiy.ZFileInputStream
     * @throws Exception
     */
    public ZFileInputStream getZFileInputStream(File file) throws Exception {
        if (!file.exists()) {
            throw new FileNotFoundException("文件不存在");
        }
        if (file.isDirectory()) {
            throw new Exception("不能为文件夹");
        }
        return new ZFileInputStream(file.getName(), new FileInputStream(file));
    }

    /**
     * 获取文件输入流
     *
     * @param list 文件集合
     * @return top.xphu.zip.entiy.ZFileInputStream
     * @throws Exception
     */
    public List<ZFileInputStream> getZFileInputStreamArray(List<File> list) throws Exception {
        LinkedList<ZFileInputStream> zFileInputStreamLinkedList = new LinkedList<>();
        for (File file : list) {
            zFileInputStreamLinkedList.add(getZFileInputStream(file));
        }
        return zFileInputStreamLinkedList;
    }


    /**
     * 压缩文件 todo 暂时不压缩
     *
     * @param response
     */
    public FilePackageCore squeeze(HttpServletResponse response) {

        return this;
    }


    /**
     * 下载 打包好的压缩文件
     *
     * @param response
     * @return
     * @throws Exception
     */
    public HttpServletResponse download(HttpServletResponse response) throws Exception {
        // 关闭文件流
        basaltFile.close();
        return FileDownloadUtils.download(basaltFile.getEmpFile(), basaltFile.getName(), response);
    }


}
